using System;
using CI.Misc;
using NUnit.Framework;
using CI;
using CI.Interfaces;

namespace Mesopotamia.UnitTests.Organism
{
    [TestFixture]
    public class CellTests
    {
        private CI.Organism.Cell _cell;
        private CI.Organism.Organism _organism;
        private CI.Organism.Amoeba _Amoeba;
        private CI.Organism.iRobot _iRobot;
        private IHostingEnvironment _hostingEnvironment;
        private UInt32 _hbCount = 199;
        private SimEnv _simEnv = SimEnv.Instance;

        /// <summary>Test Harness setup</summary>
        [SetUp]
        public void Setup()
        {
            _hostingEnvironment = new CI.Mesopotamia.MSRBHost(new MockHostingEnvironmentPhysical(), new CI.Mesopotamia.ScenarioLocalXML());
            _hostingEnvironment.HostingEnvironmentPhysical = new MockHostingEnvironmentPhysical();
            _organism = new CI.Organism.Organism(_hostingEnvironment);
            _organism.Cells = new CI.Organism.CellCollection();
        }

        /// <summary>This proceedure makes sure the cell checks the arguments</summary>
        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Organism")]
        public void CellConstructorNullOrganismException()
        {
            this._cell = new CI.Organism.Amoeba(null, Guid.NewGuid());
        }

        /// <summary>This proceedure makes sure the cell checks the arguments</summary>
        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "guid")]
        public void CellConstructorEmptyGuidException()
        {
            this._cell = new CI.Organism.Amoeba(_organism, Guid.Empty);
        }

        /// <summary>Lets Make sure when we add a cell it gets marked as active</summary>
        [Test]
        public void CellAddActiveTrue()
        {
            _cell = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            _cell.Active = false;
            _cell.AddCell();
            Assert.IsTrue(_cell.Active, "Cell should be active");
        }

        /// <summary>Lets Make sure when we delete a cell it gets marked as not active</summary>
        [Test]
        public void CellDeleteNotActiveTrue()
        {
            _cell = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            _cell.Active = false;
            _cell.AddCell();
            // now delete
            _cell.DelCell();
            Assert.IsFalse(_cell.Active, "Cell should not be active");
        }

        /// <summary>Lets Make sure when we add a cell we save its alive hb relative to the organisms</summary>
        [Test]
        public void CellAliveHeartBeatSaveTrue()
        {
            // set a heartbeat
            _organism.HeartbeatCount = _hbCount;
            // add it first
            _cell = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            _cell.Active = false;
            _cell.AddCell();
            // see if heartbeat count delete was acurate
            Assert.AreEqual(_hbCount, _cell.HBTSAlive, "Heart beat count at birth is not correct");
        }

        /// <summary>Lets Make sure when we add a cell we save its alive hb relative to the organisms</summary>
        [Test]
        public void CellDeleteHeartBeatSaveTrue()
        {
            // add it first
            _cell = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            _cell.Active = false;
            _cell.AddCell();
            // set a heartbeat
            _organism.HeartbeatCount = _hbCount;
            // delete cell
            _cell.DelCell();
            // see if heartbeat count delete was acurate
            Assert.AreEqual(_hbCount, _cell.HBTSDead, "Heart beat count at death is not correct");
        }

        /// <summary>This proceedure makes sure the cell checks the arguments</summary>
        [Test]
        public void EqualsValueTypesNullParameterFalse()
        {
            // create cell
            _cell = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            Assert.IsFalse(_cell.EqualsValueTypes(null), "result should be false, null cell comparison");
        }

        /// <summary>compares the values types of cells,actually the same cell</summary>
        [Test]
        public void EqualsValueTypesSameCellTrue()
        {
            // create cell
            _cell = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            Assert.IsTrue(_cell.EqualsValueTypes((ICell)_cell), "result should be true, they are the same");
        }

        /// <summary>compares the values types of cells,using different types should fail</summary>
        [Test]
        public void EqualsValueTypesDifferentTypesFalse()
        {
            // create cell
            ICell cell1 = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            ICell cell2 = new CI.Organism.iRobot(_organism, Guid.NewGuid());
            // give them the same guid just to check that
            cell1.Guid = cell2.Guid;
            Assert.IsFalse(cell1.EqualsValueTypes((ICell)cell2), "result should be false, they are different types");
        }

        /// <summary>test null organism being passed to it</summary>
        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Organism")]
        public void CellCreateNewCellException()
        {
            CI.Organism.Cell.CreateNewCell(0, null);
        }

        /// <summary>test to see if it created a new cell with no neural system</summary>
        [Test]
        public void CellCreateNewCellNoNeuralTrue()
        {
            Assert.IsNotNull(CI.Organism.Cell.CreateNewCell(0, _organism), "New gene not created");
        }

        /// <summary>test to see if it created a new cell with no neural system</summary>
        [Test]
        public void CellCreateNewCellWithNeuralTrue()
        {
            _organism.NeuralSystem = new CI.Organism.SimpleNeuralSystem(_organism);
            Assert.IsNotNull(CI.Organism.Cell.CreateNewCell(0, _organism), "New gene not created");
        }

        /// <summary>argument checker</summary>
        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Organism")]
        public void AmoebaMutateNullOrganism()
        {
            _Amoeba = new CI.Organism.Amoeba(_organism, Guid.NewGuid());
            _Amoeba.Mutate(0, null);
        }

        /// <summary>argument checker</summary>
        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Organism")]
        public void AmoebaCtorNullOrganism()
        {
            _Amoeba = new CI.Organism.Amoeba(null, Guid.NewGuid());
        }

        /// <summary>argument checker</summary>
        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Organism")]
        public void iRobotMutateNullOrganism()
        {
            _iRobot = new CI.Organism.iRobot(_organism, Guid.NewGuid());
            _iRobot.Mutate(0, null);
        }

        /// <summary>argument checker</summary>
        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Organism")]
        public void iRobotCtorNullOrganism()
        {
            _iRobot = new CI.Organism.iRobot(null, Guid.NewGuid());
        }
    }
}


